<?php declare(strict_types=1);

namespace App\Model;

/**
 * 公共模型Trait类
 * Trait BaseModel
 * @package App\Model
 */
trait BaseModel
{
        /**
         * 新增数据
         * @param array $arrData
         * @param string|null $strPk
         * @return mixed
         */
        public static function preserve(array $arrData, string $strPk = null)
        {
                $selfModel = self::new($arrData);
                $selfModel->save();
                if ($strPk) {
                        return $selfModel[$strPk];
                }
                return $selfModel;
        }

        /**
         * 更新数据
         * @param array $arrWhere
         * @param array $arrSet
         * @return bool
         */
        public static function renewal(array $arrWhere, array $arrSet)
        {
                if (empty($arrWhere) || empty($arrSet)) {
                        return false;
                }
                $selfModel = self::makeWhereModel($arrWhere);
                return $selfModel->update($arrSet);
        }

        /**
         * 物理删除
         * @param array $arrWhere
         * @return bool
         */
        public static function remove(array $arrWhere)
        {
                if (empty($arrWhere)) {
                        return false;
                }
                $selfModel = self::makeWhereModel($arrWhere);
                return $selfModel->delete();
        }

        /**
         * 获取单条信息
         * @param array $arrWhere
         * @param array $arrField
         * @param array $arrOrderBy
         * @param array $arrGroupBy
         * @param array $arrJoin
         * @return array
         */
        public static function getOne(array $arrWhere, array $arrField, array $arrOrderBy = [], array $arrGroupBy = [], array $arrJoin = [])
        {
                $selfModel = self::makeWhereModel($arrWhere);
                $selfModel = self::makeJoinModel($selfModel, $arrJoin);
                $selfModel = self::makeGroupByModel($selfModel, $arrGroupBy);
                $selfModel = self::makeOrderByModel($selfModel, $arrOrderBy);
                $objResult = $selfModel->first($arrField);
                if (!$objResult) return [];
                return is_array($objResult) ? $objResult : $objResult->getArrayableAttributes();
        }

        /**
         * 主键id查找单条信息
         * @param $strPrimaryKey
         * @param array $arrField
         * @return array
         */
        public static function primaryKeyFind($strPrimaryKey, array $arrField)
        {
                $objResult = self::find($strPrimaryKey, $arrField);
                if (!$objResult) return [];
                return $objResult->toArray();
        }

        /**
         * 获取某个指定字段值
         * @param array $arrWhere
         * @param string $strField
         * @param array $arrOrderBy
         * @param array $arrJoin
         * @return mixed
         */
        public static function getFieldValue(array $arrWhere, string $strField, array $arrOrderBy = [], array $arrJoin = [])
        {
                $selfModel = self::makeWhereModel($arrWhere);
                $selfModel = self::makeJoinModel($selfModel, $arrJoin);
                $selfModel = self::makeOrderByModel($selfModel, $arrOrderBy);
                return $selfModel->value($strField);
        }

        /**
         * 获取全部数据
         * @param array $arrWhere
         * @param array $arrField
         * @param array $arrOrderBy
         * @param array $arrGroupBy
         * @param array $arrJoin
         * @return mixed
         */
        public static function getAll(array $arrWhere, array $arrField, array $arrOrderBy = [], array $arrGroupBy = [], array $arrJoin = [])
        {
                $selfModel = self::makeWhereModel($arrWhere);
                $selfModel = self::makeJoinModel($selfModel, $arrJoin);
                $selfModel = self::makeGroupByModel($selfModel, $arrGroupBy);
                $selfModel = self::makeOrderByModel($selfModel, $arrOrderBy);
                return $selfModel->get($arrField)->toArray();
        }

        /**
         * 获取列表
         * @param array $arrWhere
         * @param array $arrField
         * @param int $intPage
         * @param int $intLimit
         * @param array $arrOrderBy
         * @param array $arrGroupBy
         * @param array $arrJoin
         * @return array
         */
        public static function getList(array $arrWhere, array $arrField, int $intPage, int $intLimit, array $arrOrderBy = [], array $arrGroupBy = [], array $arrJoin = [])
        {
                $selfModel = self::makeWhereModel($arrWhere);
                $selfModel = self::makeJoinModel($selfModel, $arrJoin);
                $selfModel = self::makeGroupByModel($selfModel, $arrGroupBy);
                $intTotal = $selfModel->count();
                $selfModel = self::makeOrderByModel($selfModel, $arrOrderBy);
                $arrList = $selfModel->forPage($intPage, $intLimit)->get($arrField)->toArray();
                return [
                        'total' => $intTotal,
                        'list' => $arrList
                ];
        }

        /**
         * 获取条数 不带总数
         * @param array $arrWhere
         * @param array $arrField
         * @param int $intPage
         * @param int $intLimit
         * @param array $arrOrderBy
         * @param array $arrGroupBy
         * @param array $arrJoin
         */
        public static function getLimit(array $arrWhere, array $arrField, int $intPage, int $intLimit, array $arrOrderBy = [], array $arrGroupBy = [], array $arrJoin = [])
        {
                $selfModel = self::makeWhereModel($arrWhere);
                $selfModel = self::makeJoinModel($selfModel, $arrJoin);
                $selfModel = self::makeGroupByModel($selfModel, $arrGroupBy);
                $selfModel = self::makeOrderByModel($selfModel, $arrOrderBy);
                $arrList = $selfModel->forPage($intPage, $intLimit)->get($arrField)->toArray();
                return $arrList;
        }

        /**
         * 获取总数
         * @param array $arrWhere
         * @param array $arrGroupBy
         * @param array $arrJoin
         * @return mixed
         */
        public static function getTotal(array $arrWhere = [], array $arrGroupBy = [], array $arrJoin = [])
        {
                $selfModel = self::makeWhereModel($arrWhere);
                $selfModel = self::makeJoinModel($selfModel, $arrJoin);
                $selfModel = self::makeGroupByModel($selfModel, $arrGroupBy);
                return $selfModel->count();
        }

        /**
         * 获取列
         * @param array $arrWhere
         * @param string $strColumn
         * @param array $arrOrderBy
         * @param string|null $strKeyBy
         * @param array $arrGroupBy
         * @param array $arrJoin
         * @return mixed
         */
        public static function getColumn(array $arrWhere, string $strColumn, array $arrOrderBy = [], string $strKeyBy = null, array $arrGroupBy = [], array $arrJoin = [])
        {
                $selfModel = self::makeWhereModel($arrWhere);
                $selfModel = self::makeJoinModel($selfModel, $arrJoin);
                $selfModel = self::makeGroupByModel($selfModel, $arrGroupBy);
                $selfModel = self::makeOrderByModel($selfModel, $arrOrderBy);
                $objResult = $strKeyBy ? $selfModel->pluck($strColumn, $strKeyBy) : $selfModel->pluck($strColumn);
                return $objResult->toArray();
        }

        /**
         * 递归获取所有子级数据
         * @param array $arrWhere
         * @param array $arrField
         * @param string $strIdField
         * @param array $arrOrderBy
         * @param array $arrReturn
         * @return array
         */
        public static function recursionFindChild(array $arrWhere, array $arrField, $strIdField = 'id', array $arrOrderBy = [], array $arrReturn = [])
        {
                $arrData = self::getAll($arrWhere, $arrField, $arrOrderBy);
                if ($arrData) {
                        $arrReturn = array_merge($arrReturn, $arrData);
                        $arrId = [];
                        foreach ($arrData as $v) {
                                $arrId[] = $v[$strIdField];
                        }
                        foreach ($arrWhere as $k => $v) {
                                if ($v[0] == 'whereIn') {
                                        $arrWhere[$k] = ['whereIn', 'pid', $arrId];
                                }
                        }
                        $arrReturn = self::recursionFindChild($arrWhere, $arrField, $strIdField, $arrOrderBy, $arrReturn);
                }
                return $arrReturn;
        }

        /**
         * 创建条件模型
         * @param array $arrWhere
         * @return BaseModel
         */
        public static function makeWhereModel(array $arrWhere)
        {
                $selfModel = new self;
                if ($arrWhere) {
                        $selfModel = $selfModel->where($arrWhere);
                }
                return $selfModel;
        }

        /**
         * 创建排序模型
         * @param $selfModel
         * @param array $arrOrderBy
         * @return mixed
         */
        public static function makeOrderByModel($selfModel, array $arrOrderBy = [])
        {
                if ($arrOrderBy) {
                        foreach ($arrOrderBy as $k => $v) {
                                $selfModel = $selfModel->orderBy($k, $v);
                        }
                }
                return $selfModel;
        }

        /**
         * 创建分组模型
         * @param $selfModel
         * @param array $arrGroupBy
         * @return mixed
         */
        public static function makeGroupByModel($selfModel, array $arrGroupBy = [])
        {
                if ($arrGroupBy) {
                        foreach ($arrGroupBy as $v) {
                                $selfModel = $selfModel->groupBy($v);
                        }
                }
                return $selfModel;
        }

        /**
         * 创建表连接模型
         * @param $selfModel
         * @param array $arrJoin
         * @return mixed
         */
        public static function makeJoinModel($selfModel, array $arrJoin = [])
        {
                if ($arrJoin) {
                        foreach ($arrJoin as $k => $v) {
                                $strJoinType = isset($v['type']) ? $v['type'] : 'inner';
                                $arrJoinWhere = $v['where'];
                                if ($strJoinType == 'left') {
                                        $selfModel = $selfModel->leftJoin($v['table'], $arrJoinWhere[0], $arrJoinWhere[1], $arrJoinWhere[2]);
                                } else if ($strJoinType == 'right') {
                                        $selfModel = $selfModel->rightJoin($v['table'], $arrJoinWhere[0], $arrJoinWhere[1], $arrJoinWhere[2]);
                                } else {
                                        $selfModel = $selfModel->join($v['table'], $arrJoinWhere[0], $arrJoinWhere[1], $arrJoinWhere[2]);
                                }
                        }
                }
                return $selfModel;
        }
}
